/*
 * EventDispatcher.cpp
 *
 *  Created on: 2013-8-31
 *  Author: xnan
 */

#include <iostream>
#include <cstring>
#include <string>
#include <typeinfo>

#include "EventDispatcher.h"

NS_XNL_BEGIN

EventDispatcher::EventDispatcher()
{
}

EventDispatcher::~EventDispatcher()
{
    this->clearEventListenerInfo();
}

void EventDispatcher::addEventListener(
    Object * p_target,
    const char * p_eventName,
    XNint p_eventType,
    EventCallback p_callback,
    XNbool p_usePrev,
    XNint p_priority,
    Object * p_userdata
    )
{
    std::list<EventListenerInfo*>::iterator iter = this->m_eventListenerInfos.begin();
    std::list<EventListenerInfo*>::iterator insertPos = iter;
    while( iter != this->m_eventListenerInfos.end() )
    {
        EventListenerInfo * tmpInfo = *iter;
        if( strcmp( p_eventName, tmpInfo->m_eventName ) == 0
         && p_eventType == tmpInfo->m_eventType
         && p_callback == tmpInfo->m_callback
         && p_usePrev == tmpInfo->m_useImmed ) throw std::logic_error( XN_RUNTIME_ERR_STR( "Events have been added!" ) );
        if( p_priority >= tmpInfo->m_priority ) insertPos = iter;
        ++ iter;
    }
    
    EventListenerInfo * newInfo = new EventListenerInfo();
    XN_RETAIN_ASSIGN( newInfo->m_target, p_target );
    newInfo->m_eventName = p_eventName;
    newInfo->m_eventType = p_eventType;
    newInfo->m_priority = p_priority;
    XN_RETAIN_ASSIGN( newInfo->m_userdata, p_userdata );
    newInfo->m_callback = p_callback;
    
    m_eventListenerInfos.insert( insertPos, newInfo );
}

void EventDispatcher::removeEventListener(
	const char * p_eventName,
	XNint p_eventType,
	EventCallback p_callback
	)
{
	XNbool isDel = false;
    std::list<EventListenerInfo*>::iterator iter = this->m_eventListenerInfos.begin();
    while( iter != this->m_eventListenerInfos.end() )
    {
        EventListenerInfo * tmpInfo = *iter;
        
        if( typeid(*p_eventName).name() == tmpInfo->m_eventName )
        {
        	if(/*这里判断是否符合删除的条件*/
        	    p_eventType == 0
        	    || ( p_eventType == tmpInfo->m_eventType
        	         && (p_callback == NULL || p_callback == tmpInfo->m_callback)
        	       )
        	)
        	{
        		isDel = true;
        	}
        	
        	if( isDel )
			{
        		XN_RELEASE( tmpInfo->m_target );
				XN_RELEASE( tmpInfo->m_userdata );
				iter = m_eventListenerInfos.erase( iter );
			}
        }
        else
        {
        	++ iter;
        }
    }
}

void EventDispatcher::removeEventListener(
	const char * p_eventName,
	XNint p_eventType,
	EventCallback p_callback,
	XNbool p_useImmed
	)
{
	XNbool isDel = false;
	std::list<EventListenerInfo*>::iterator iter = this->m_eventListenerInfos.begin();
	while( iter != this->m_eventListenerInfos.end() )
	{
		EventListenerInfo * tmpInfo = *iter;
		
		if( typeid(*p_eventName).name() == tmpInfo->m_eventName )
		{
			if(/*这里判断是否符合删除的条件*/
				(
				p_eventType == 0
				|| ( p_eventType == tmpInfo->m_eventType
					 && (p_callback == NULL || p_callback == tmpInfo->m_callback)
				   )
				)
				&& p_useImmed == tmpInfo->m_useImmed
			)
			{
				isDel = true;
			}
			
			if( isDel )
			{
				XN_RELEASE( tmpInfo->m_target );
				XN_RELEASE( tmpInfo->m_userdata );
				iter = m_eventListenerInfos.erase( iter );
			}
			else ++ iter;
		}
		else
		{
			++ iter;
		}
	}
}

void EventDispatcher::dispatchEvent( Event * p_event )
{
	Object * obj = p_event->getTarget();
	p_event->setTarget( this );
    this->handleEvent( p_event, true );
    this->handleEvent( p_event, false );
    p_event->setTarget( obj );
}

void EventDispatcher::handleEvent( Event * p_event, XNbool p_useImmed )
{
	std::list<EventListenerInfo*>::iterator iter = m_eventListenerInfos.begin();
	while( iter != this->m_eventListenerInfos.end() )
	{
		EventListenerInfo * tmpInfo = *iter;
		if( p_event != NULL
		 && typeid(*p_event).name() == tmpInfo->m_eventName
		 && p_event->getEventType() == tmpInfo->m_eventType
		 && p_useImmed == tmpInfo->m_useImmed
		)
		{
			p_event->setCurrentTarget( tmpInfo->m_target );
			tmpInfo->m_callback( tmpInfo->m_target, p_event );
		}
		iter++;
	}
}

void EventDispatcher::clearEventListenerInfo()
{
    std::list<EventListenerInfo*>::iterator iter = this->m_eventListenerInfos.begin();
    while( iter != this->m_eventListenerInfos.end() )
    {
        EventListenerInfo * tmpInfo = *iter;
        XN_RELEASE( tmpInfo->m_target );
        XN_RELEASE( tmpInfo->m_userdata );
        iter = m_eventListenerInfos.erase( iter );
        delete tmpInfo;
    }
}

NS_XNL_END
